【小ネタ】簡単にLambda関数のコンテナ内でコマンドを実行する方法
はじめに
こんにちは、中山です。
先程ネットサーフィン(死語)していたところ面白そうなツールを見つけました。作者はLambda関数のデプロイツールApexを作成した方です。
このツールを使うとLambda関数のコンテナ内でシェルを起動させ、コマンドを実行できます。普段はあまり意識することのないLambda関数のコンテナの内部を垣間見えたのでレポートします。
インストール方法
READMEに書いてあるとおり go get
コマンドでインストール可能です。
$ go get github.com/apex/apex-shell
以下のコマンドを実行してインストールされたことを確認してください。
$ apex-shell -version 1.0.0
環境によって異なりますが、失敗するかと思います。例えば以下のように「XXがない」と言われたら、おとなしくそのパッケージを go get
でインストールしてください。
$ apex-shell -version FATAL[0000] error: build hook: main.go:8:2: cannot find package "github.com/apex/go-apex" in any of: /usr/local/Cellar/go/1.6/libexec/src/github.com/apex/go-apex (from $GOROOT) /Users/knakayama/.go/src/github.com/apex/go-apex (from $GOPATH) /Users/knakayama/.go/src/github.com/apex/log/handlers/logfmt/logfmt.go:10:2: cannot find package "github.com/go-logfmt/logfmt" in any of: /usr/local/Cellar/go/1.6/libexec/src/github.com/go-logfmt/logfmt (from $GOROOT) /Users/knakayama/.go/src/github.com/go-logfmt/logfmt (from $GOPATH) $ go get github.com/apex/go-apex
最終的にバージョン番号が表示されたらインストール完了です。
下準備
apex-shell
は Apex のプロジェクト上で実行させる必要があります。 project.json
からさまざまな情報を取得しているためです。そのため一度プロジェクトを作成する必要があります。作成方法は以下のとおりです。入力する <project-name>
と <project-description>
は適当なものを入力してください。
$ apex init _ ____ _______ __ / \ | _ \| ____\ \/ / / _ \ | |_) | _| \ / / ___ \| __/| |___ / \ /_/ \_\_| |_____/_/\_\ Enter the name of your project. It should be machine-friendly, as this is used to prefix your functions in Lambda. Project name: <project-name> Enter an optional description of your project. Project description: <project-description> [+] creating IAM test_lambda_function role [+] creating IAM test_lambda_logs policy [+] attaching policy to lambda_function role. [+] creating ./project.json [+] creating ./functions Setup complete, deploy those functions! $ apex deploy
Apexのインストール方法は以下のエントリを参照してください。
正常にプロジェクトが作成されると以下のようにファイルとLambda関数用IAM Roleが作成されます。
$ tree . . ├── functions │ └── hello │ └── index.js └── project.json 2 directories, 2 files
コンテナ内に突入
準備が整ったのでいよいよ apex-shell
コマンドを実行してみましょう。
$ apex-shell INFO[0004] creating function env= function=repl INFO[0007] created alias current env= function=repl version=3 INFO[0007] function created env= function=repl name=test_repl version=3 apex>
apex-shell
と入力するとREPL用のLambda関数が起動し、シェルが立ち上がります。続いて、適当にコマンドを実行してみましょう。
apex> whoami sbx_user1053 apex> pwd /var/task apex> ls -l total 3236 -rw-rw-r-- 1 slicer 497 185 Jan 1 2098 _apex_index.js -rw-rw-r-- 1 slicer 497 4710 Jan 1 2098 byline.js -rw-rw-r-- 1 slicer 497 837 Jan 1 2098 index.js -rwxr-xr-x 1 slicer 497 3293168 Jan 1 2098 main -rwxr-xr-x 1 slicer 497 624 Jan 1 2098 main.go
コンテナ内で利用可能なコマンドは実行可能なようです。当たり前ですが。
以前AWS Lambdaをいろいろ暴くという記事が一部界隈で話題になっていました。このときはLambda関数内で子プロセスを起動させコマンドを実行する、という方法でコンテナ内を調査していました。今回はREPL形式でコマンドを実行できるので、連続してコマンドを実行可能です。Lambda関数のコンテナを調べたい場合に捗るかもしれません。まぁあまりないかもしれませんが。
お遊びが終わったら先程作成したIAM Roleを削除しておきましょう。
どうやって動作しているのか
apex-shell
のソースコードは200行程度です。覗いてみるとforループでLambda関数を起動させていることが確認できます。つまり、ローカルPCで入力したコマンドをLambda関数に渡して起動し、そのコマンドを実行、最終的に結果をローカルに表示させるという結構原始的な仕組みになっているようです。なので、実行内容的には先のリンク先と同じです。
まとめ
いかがだったでしょうか。
個人的には面白いツールを発見した感があります。普段意識してなかったものに触れられたのでそこそこ楽しめました。
本エントリがみなさんの参考になれば幸いです。